package goTeam.up.cs301.go;

import goTeam.up.cs301.game.infoMsg.GameInfo;
import goTeam.up.cs301.game.infoMsg.IllegalMoveInfo;
import goTeam.up.cs301.game.infoMsg.NotYourTurnInfo;
import android.graphics.Point;

/**
 * A computerized go player that recognizes an immediate win
 * or loss, and plays appropriately.  If there is not an immediate win
 * (which it plays) or loss (which it blocks), it moves randomly.
 * 
 * I have seen some evidence that it occasionally does not block when
 * it should. Timing-related?
 * 
 * @author Steven R. Vegdahl
 * @author Ryan Gasik
 * @version December 2013
 * 
 */
public class GoComputerPlayer2 extends GoComputerPlayer
{
	
	private GoState state;
	private GoState lastState;
	char color;
	/**
	 * constructor for a computer player
	 * 
	 * @param name
	 * 		the player's name
	 */
	public GoComputerPlayer2(String name) {
		// invoke superclass constructor
		super(name);
		color = (this.playerNum == 0 ? 'b' : 'w');
	}// constructor

	/**
	 * perform any initialization that needs to be done after the player
	 * knows what their game-position and opponents' names are.
	 */
	protected void initAfterReady() {
		// initialize our piece
		piece = "XO".charAt(playerNum);
	}// initAfterReady

	/**
	 * Called when the player receives a game-state (or other info) from the
	 * game.
	 * 
	 * @param gameInfo
	 * 		the message from the game
	 */
	@Override
	protected void receiveInfo(GameInfo info) {

		if (info instanceof IllegalMoveInfo){
			System.out.println("Attempted to make illegal move. Falling back to a random move");
			GoComputerPlayer1.makeRandomMove(info, game, this);
			return;
		}

		// if it's not a GoState message, ignore it; otherwise
		// cast it
		if (!(info instanceof GoState) || info instanceof NotYourTurnInfo ) return;
		
		System.out.println("AI Attempting Move");
		if (info instanceof IllegalMoveInfo){
			GoComputerPlayer1.makeRandomMove(info, game, this);
			return;
		}
		
		

		lastState = state;
		state = (GoState)info;
		if (state.getWhoseMove() != this.playerNum)
			return;
		findCapture(state, 'y');    	// pick x and y positions at random (0-2))
		int xVal = (int)((GoHumanPlayer1.NUM_LINES - 1)*Math.random());
    	int yVal = (int)((GoHumanPlayer1.NUM_LINES - 1)*Math.random());
		
    	Point a = findAdjacentToBoth('b','b');
    	if (a.x != -1 )
    	{
    		xVal = a.y;
    		yVal = a.x;
    	}
    	boolean lib = state.hasLiberties(xVal, yVal, color);

    	// Submit our move to the game object. We haven't even checked it it's
    	// our turn, or that that position is unoccupied. If it was not our turn,
    	// we'll get a message back that we'll ignore. If it was an illegal move,
    	// we'll end up here again (and possibly again, and again). At some point,
    	// we'll end up randomly pick a move that is legal.
    	

    	// We just check to see if the last move was a pass, and if so we pass 90% of the time.  	
    	System.out.println("AI Move attempt complete");
    	game.sendAction(new GoMoveAction(this, yVal, xVal, info instanceof GoState ? ((GoState)info).wasLastMoveAPass() ^ (Math.random() < .1) : false));

	}// receiveInfo

	/**
	 * Finds a space adjacent to both color1 and color2.
	 * @param color1 First color.
	 * @param color2 Second color.
	 * @return Point to the location of the space.
	 */
	public Point findAdjacentToBoth(char color1, char color2)
	{
		int x = -1;
		int y = -1;
		
		for (int i = 0; i < 19; i++)
		{
			for (int j = 0; j < 19; j++)
			{
				if (state.getPiece(i, j) == ' ')
				{
					char above = state.getPiece(i-1, j);
					char below = state.getPiece(i+1, j);
					char left = state.getPiece(i, j-1);
					char right = state.getPiece(i, j+1);
					
					if( (((above==color1)||below==color2) && (left == color2)||(right == color2))
						||((left == color1 || right == color1) && (above == color2 || below == color2))
						||((above == color1 && below == color2) || (below == color1 && above == color2))
						||((left == color1 && right == color2) || (right == color2 && left == color2)))
						{
							if (state.emptySpaceHasLiberties(i, j, 'w'))
							{
								x = i;
								y = j;
							}
						}
														
				}
			}
		}
		return (new Point(x,y));
	}//findAdjacentToBoth
	
	/**
	 * finds a capturing move for the player
	 * 
	 * @param state  the state of the game
	 * @param thePiece  the piece we're trying to place ('X' or 'O') for a
	 *   win
	 * @return  If a winning move was found, a Point object containing
	 *   the coordinates.  If no winning move was found, null.
	 */
	private Point findCapture(GoState state, char thePiece) {
		int x = 0, y = 0;
        for (int i=0; i < 18; i++)
        {
        	for (int j=0; j < 18; j++)
        	{
        		//First, find an enemy's threatened piece.
        		if ((state.getPiece(i,j) != color) && !state.hasLiberties(i, j, (this.playerNum == 0 ? 'w' : 'b')))
        		{
        			//Find the last liberty and take it. 
        			if (state.isFree(i-1, j))   
        			{
        				x = i-1;
        				y = j;
        			}
        			else if (state.isFree(i+1, j))
        			{
        				x = i+1;
        				y = j;
        			}
        			else if (state.isFree(i, j-1))
        			{
        				x = i;
        				y = j-1;
        			}
        			else if (state.isFree(i, j+1))
        			{
        				x = i;
        				y = j+1;
        			}
        		}
        	}
        }
	    
		// the winning move--initialized to null because we haven't found
		// one yet
		// return whatever we've found--either a winning move or null
		return (new Point(x,y));
	}// findCapture
	


}
